﻿using static System.Net.Mime.MediaTypeNames;
using System.Reflection;
using Castle.DynamicProxy;

namespace Consolo
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");

            //Itest itest = new TestOne();
            //GetType(itest);

            var proxyGenerator = new ProxyGenerator();
            // 使用接口代理，并绑定实际实现类
            Itest proxy = proxyGenerator.CreateInterfaceProxyWithTarget<Itest>(
                new TestTwo(),       // 实现类实例
                new LoggingInterceptor() // 拦截器
            );
            // 通过反射拿到目标实例（需要强转回 IProxyTargetAccessor）
            var targetAccessor = (Castle.DynamicProxy.IProxyTargetAccessor)proxy;
            var target = targetAccessor.DynProxyGetTarget();
            var xw = target.GetType();
            var x = proxy.GetType();
        }

        public static IEnumerable<Type> GetType(object realize)
        {
            var inter = realize.GetType().GetInterfaces().Any(x => x == typeof(Itest));
            var intetfaces = realize.GetType().GetInterfaces().Where(x => x == typeof(Itest)).ToList();
            if (!inter)
                return null;
            //所有
            var allClasses = AppDomain.CurrentDomain
            .GetAssemblies()
            .SelectMany(a => a.GetTypes())
                      .Where(t => t.IsClass && !t.IsAbstract && intetfaces.Any(x => x.IsAssignableFrom(t))
                      && t.GetCustomAttributes<TestsAttribute>() != null).ToList();
            //获取当前
            var current = allClasses.Where(x => x == realize.GetType()).ToList();
            return current;
        }
    }

    public class LoggingInterceptor : IInterceptor
    {
        public void Intercept(IInvocation invocation)
        {
            Console.WriteLine($"[Before] Calling method: {invocation.Method.Name}");
            invocation.Proceed();
            Console.WriteLine($"[After] Method {invocation.Method.Name} executed");
        }
    }

    public class TestsAttribute : Attribute { }


    public interface Itest
    {

    }

    [Tests()]
    public class TestOne : Itest
    {

    }

    [Tests()]
    public class TestTwo : Itest
    {

    }
}
